﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MainForm.cs" company="Elilink">
//   Defor
// </copyright>
// <summary>
//   The main form.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace STDULibrary
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Drawing;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Windows.Forms;

    using STDULibrary.Objects;
    using STDULibrary.Properties;
    using STDULibrary.Tools;

    /// <summary>
    ///     The main form.
    /// </summary>
    internal partial class MainForm : Form
    {
        #region Constants

        /// <summary>
        ///     The settings file name
        /// </summary>
        private const string SettingsFileName = "FilesViewerState.xml";

        #endregion

        #region Fields

        /// <summary>
        ///     The filter by folder name.
        /// </summary>
        private bool filterByFolderName;

        /// <summary>
        ///     The is filtered.
        /// </summary>
        private bool isFiltered;

        /// <summary>
        ///     The is filtered by extension
        /// </summary>
        private bool isFilteredByExtension;

        /// <summary>
        ///     The search aborted
        /// </summary>
        private bool searchAborted;

        /// <summary>
        ///     The sort by extension
        /// </summary>
        private bool sortByExtension;

        /// <summary>
        ///     The sort by folder name
        /// </summary>
        private bool sortByFolderName;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="MainForm" /> class.
        /// </summary>
        public MainForm()
        {
            this.InitializeComponent();
            this.sortByExtension = false;
            this.sortByFolderName = false;
            this.isFiltered = false;
            this.filterByFolderName = false;
            this.isFilteredByExtension = false;
        }

        #endregion

        #region Properties

        /// <summary>
        ///     Gets the extensions labels.
        /// </summary>
        /// <value>The extensions labels.</value>
        private IEnumerable<Label> ExtensionsLabels
        {
            get
            {
                Control.ControlCollection controls = this.gbxInitialData.Controls;
                return
                    controls.Cast<object>().OfType<Label>().Where(label => label.Name.StartsWith("lblFormat")).ToList();
            }
        }

        /// <summary>
        ///     Gets the filtered books count.
        /// </summary>
        private int FilteredBooksCount
        {
            get
            {
                return this.FilteredFilledFolders.Sum(folder => folder.Books.Count);
            }
        }

        /// <summary>
        ///     Gets the filtered filled folders.
        /// </summary>
        /// <value>The filtered filled folders.</value>
        private IEnumerable<Folder> FilteredFilledFolders
        {
            get
            {
                if (!this.TotalFilledFolders.Any())
                {
                    return new List<Folder>();
                }

                List<Folder> folders = this.TotalFilledFolders.ToList();

                if (this.isFiltered)
                {
                    folders = this.FilterBooksByNameAndFolder(folders);
                    folders = this.FilterBooksByExtension(folders);
                }

                return folders;
            }
        }

        /// <summary>
        ///     Gets or sets the collection.
        /// </summary>
        private Folder FolderStorage { get; set; }

        /// <summary>
        ///     Gets the last index of the row.
        /// </summary>
        /// <value>The last index of the row.</value>
        private int LastRowIndex
        {
            get
            {
                return this.gridBooks.Rows.Count - 1;
            }
        }

        /// <summary>
        ///     Gets the total books count.
        /// </summary>
        private int TotalBooksCount
        {
            get
            {
                return this.TotalFilledFolders.Sum(folder => folder.Books.Count);
            }
        }

        /// <summary>
        ///     Gets the total filled folders.
        /// </summary>
        /// <value>The total filled folders.</value>
        private IEnumerable<Folder> TotalFilledFolders
        {
            get
            {
                if (this.FolderStorage == null)
                {
                    return new List<Folder>();
                }

                var folders = new List<Folder>();
                this.GetFoldersWithBooks(folders, this.FolderStorage);
                folders = this.sortByFolderName
                              ? folders.OrderBy(f => f.FolderName).ToList()
                              : folders.OrderBy(f => f.FolderPath).ToList();

                return folders;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Adds the books to folder.
        /// </summary>
        /// <param name="folder">The folder.</param>
        /// <param name="icons">The icons.</param>
        /// <param name="extensions">The extensions.</param>
        private void AddBooksToFolder(Folder folder, Dictionary<string, Icon> icons, List<string> extensions)
        {
            var directoryInfo = new DirectoryInfo(folder.FolderPath);
            if (!directoryInfo.CanRead())
            {
                return;
            }

            foreach (
                FileInfo fileInfo in directoryInfo.GetFilesByExtensions(extensions.ToArray()))
            {
                folder.Books.Add(
                    new Book
                        {
                            NameAndPath = fileInfo.FullName, 
                            NameAndExtension = fileInfo.Name, 
                            Name =
                                fileInfo.Name.Substring(
                                    0, 
                                    fileInfo.Name.LastIndexOf(fileInfo.Extension, StringComparison.Ordinal)), 
                            Extension = fileInfo.Extension, 
                            Image = icons[fileInfo.Extension]
                        });
            }
        }

        /// <summary>
        /// Adds the current folder to grid.
        /// </summary>
        /// <param name="folder">
        /// The folder.
        /// </param>
        private void AddCurrentFolderToGrid(Folder folder)
        {
            if (folder == null || !folder.Books.Any())
            {
                return;
            }

            int currentCount = int.Parse(this.lblTotalBooks.Text);
            currentCount += folder.Books.Count;
            this.lblTotalBooks.Text = this.lblFilteredBooks.Text = currentCount.ToString(CultureInfo.InvariantCulture);

            this.gridBooks.Rows.Add(Resources.Folder, folder.FolderName);
            DataGridViewRow currentRow = this.gridBooks.Rows[this.LastRowIndex];
            currentRow.DefaultCellStyle.BackColor = Color.LightCyan;
            currentRow.DefaultCellStyle.SelectionBackColor = Color.LightCyan;
            currentRow.Cells[1].ToolTipText = folder.FolderPath;
            foreach (Book book in folder.Books)
            {
                this.gridBooks.Rows.Add(book.Image, book.Name);
                DataGridViewRow bookRow = this.gridBooks.Rows[this.LastRowIndex];
                bookRow.Cells[1].ToolTipText = book.NameAndPath;
            }
        }

        /// <summary>
        /// Handles the DoWork event of the BackgroundWorker control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.
        /// </param>
        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            var inputData = (BackGroundWorkerInputData)e.Argument;
            Folder initialCollection = inputData.InitialFolder;
            Dictionary<string, Icon> icons = inputData.IconsCollection;
            List<string> extensions = inputData.Extensions;
            var worker = (BackgroundWorker)sender;
            this.FillDirectories(worker, initialCollection, icons, extensions);
        }

        /// <summary>
        /// Handles the ProgressChanged event of the BackgroundWorker control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.
        /// </param>
        private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            var folder = (Folder)e.UserState;
            this.lblStatus.Text = string.Format("Searching in {0}", folder.FolderPath);
            this.AddCurrentFolderToGrid(folder);
        }

        /// <summary>
        /// Handles the RunWorkerCompleted event of the BackgroundWorker control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event
        ///     data.
        /// </param>
        private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.btnGo.Text = string.Format("Go!");
            this.gbxFilters.Enabled = true;
            this.BindData();
            if (this.searchAborted)
            {
                this.lblStatus.Text = string.Format("Search aborted.");
                this.searchAborted = false;
            }
            else
            {
                this.lblStatus.Text = string.Format("Storage update complete.");
            }
        }

        /// <summary>
        ///     The bind data.
        /// </summary>
        private void BindData()
        {
            this.gridBooks.Rows.Clear();
            this.UpdateBooksCount();

            foreach (Folder folder in this.FilteredFilledFolders)
            {
                this.gridBooks.Rows.Add(Resources.Folder, folder.FolderName);
                DataGridViewRow currentRow = this.gridBooks.Rows[this.LastRowIndex];
                currentRow.DefaultCellStyle.BackColor = Color.LightCyan;
                currentRow.DefaultCellStyle.SelectionBackColor = Color.LightCyan;
                currentRow.Cells[1].ToolTipText = folder.FolderPath;
                foreach (Book book in folder.Books)
                {
                    this.gridBooks.Rows.Add(book.Image, book.Name);
                    DataGridViewRow bookRow = this.gridBooks.Rows[this.LastRowIndex];
                    bookRow.Cells[1].ToolTipText = book.NameAndPath;
                }
            }
        }

        /// <summary>
        ///     Binds the extensions combobox.
        /// </summary>
        private void BindExtensionsCombobox()
        {
            this.comboExtensions.Items.Add("All");
            foreach (string extension in ExtensionsHelper.GetAvailableExtensions().OrderBy(e => e))
            {
                this.comboExtensions.Items.Add(extension);
            }

            this.comboExtensions.SelectedIndex = 0;
        }

        /// <summary>
        /// BTNs the clear filter_ click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The <see cref="System.EventArgs"/> instance containing the event data.
        /// </param>
        private void BtnClearFilter_Click(object sender, EventArgs e)
        {
            this.txtFilter.TextChanged -= this.TxtFilter_TextChanged;
            this.cbxFilterByFolder.CheckedChanged -= this.CbxFilterByFolder_CheckedChanged;
            this.comboExtensions.SelectedIndexChanged -= this.ComboExtensions_SelectedIndexChanged;
            this.txtFilter.Text = string.Empty;
            this.cbxFilterByFolder.Checked = false;
            this.comboExtensions.SelectedIndex = 0;
            this.isFiltered = false;
            this.isFilteredByExtension = false;
            this.filterByFolderName = false;
            this.BindData();
            this.txtFilter.TextChanged += this.TxtFilter_TextChanged;
            this.cbxFilterByFolder.CheckedChanged += this.CbxFilterByFolder_CheckedChanged;
            this.comboExtensions.SelectedIndexChanged += this.ComboExtensions_SelectedIndexChanged;
        }

        /// <summary>
        /// Handles the Click event of the BtnGo control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void BtnGo_Click(object sender, EventArgs e)
        {
            if (this.backgroundWorker.IsBusy)
            {
                this.searchAborted = true;
                this.backgroundWorker.CancelAsync();
                return;
            }

            if (string.IsNullOrEmpty(this.txtLibraryPath.Text) || !Directory.Exists(this.txtLibraryPath.Text))
            {
                string message = string.Format("Library path is not filled or specified directory does not exist.");
                MessageBoxEx.Show(this, message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            this.btnGo.Text = string.Format("Stop");
            this.gbxFilters.Enabled = false;
            this.gridBooks.Rows.Clear();

            this.FolderStorage = new Folder(this.txtLibraryPath.Text);
            var extensions =
                this.ExtensionsLabels.Where(l => l.Font.Bold)
                    .SelectMany(l => l.Text.Replace(")", string.Empty).Split('('))
                    .ToList();
            this.backgroundWorker.RunWorkerAsync(
                new BackGroundWorkerInputData(this.FolderStorage, ExtensionsHelper.GetResourcesIcons, extensions));
        }

        /// <summary>
        /// Handles the Click event of the BtnLibraryPath control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void BtnLibraryPath_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(this.txtLibraryPath.Text))
            {
                this.dlgFolderBrowser.SelectedPath = this.txtLibraryPath.Text;
            }

            if (this.dlgFolderBrowser.ShowDialog(this) == DialogResult.OK)
            {
                this.txtLibraryPath.Text = this.dlgFolderBrowser.SelectedPath;
            }
        }

        /// <summary>
        /// Handles the Click event of the BtnSTDUExecutablePath control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void BtnSTDUExecutablePath_Click(object sender, EventArgs e)
        {
            string currentPath = this.txtSTDUViewerPath.Text;
            if (!string.IsNullOrEmpty(currentPath))
            {
                this.dlgOpenFile.InitialDirectory = currentPath.Substring(0, currentPath.LastIndexOf('\\') + 1);
                this.dlgOpenFile.FileName = currentPath.Substring(currentPath.LastIndexOf('\\') + 1);
            }

            if (this.dlgOpenFile.ShowDialog(this) == DialogResult.OK)
            {
                if (!this.CheckPropertiesFile(this.dlgOpenFile.FileName))
                {
                    string message =
                        string.Format(
                            "Probably selected application is not a valid STDU Viewer instance. Can't find default settings file '{0}' in the directory '{1}'", 
                            SettingsFileName, 
                            this.dlgOpenFile.FileName.Substring(0, this.dlgOpenFile.FileName.LastIndexOf('\\') + 1));
                    MessageBoxEx.Show(this, message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                this.txtSTDUViewerPath.Text = this.dlgOpenFile.FileName;
            }
        }

        /// <summary>
        /// The cbx filter by folder_ checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void CbxFilterByFolder_CheckedChanged(object sender, EventArgs e)
        {
            this.filterByFolderName = this.cbxFilterByFolder.Checked;
            this.BindData();
        }

        /// <summary>
        /// Handles the CheckedChanged event of the CbxSortByExtension control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void CbxSortByExtension_CheckedChanged(object sender, EventArgs e)
        {
            this.sortByExtension = this.cbxSortByExtension.Checked;
            this.BindData();
        }

        /// <summary>
        /// Handles the CheckedChanged event of the CbxSortByFolderPath control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void CbxSortByFolderPath_CheckedChanged(object sender, EventArgs e)
        {
            this.sortByFolderName = this.cbxSortByFolderName.Checked;
            this.BindData();
        }

        /// <summary>
        /// Checks the properties file.
        /// </summary>
        /// <param name="fileName">
        /// Name of the file.
        /// </param>
        /// <returns>
        /// <c>true</c> if XXXX, <c>false</c> otherwise
        /// </returns>
        private bool CheckPropertiesFile(string fileName)
        {
            string stduFolder = fileName.Substring(0, fileName.LastIndexOf('\\') + 1);
            string settingsFilePath = string.Concat(stduFolder, SettingsFileName);
            if (!File.Exists(settingsFilePath))
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the ComboExtensions control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void ComboExtensions_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.comboExtensions.SelectedIndex != 0)
            {
                this.isFiltered = true;
                this.isFilteredByExtension = true;
            }
            else
            {
                this.isFiltered = !string.IsNullOrEmpty(this.txtFilter.Text);
                this.isFilteredByExtension = false;
            }

            this.BindData();
        }

        /// <summary>
        /// Handles the Click event of the ExtensionLabel control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void ExtensionLabel_Click(object sender, EventArgs e)
        {
            var label = (Label)sender;
            label.Font = new Font(label.Font, label.Font.Bold ? FontStyle.Regular : FontStyle.Bold);
        }

        /// <summary>
        /// Fills the directories.
        /// </summary>
        /// <param name="worker">The worker.</param>
        /// <param name="folder">The folder.</param>
        /// <param name="icons">The icons.</param>
        /// <param name="extensions">The extensions.</param>
        private void FillDirectories(BackgroundWorker worker, Folder folder, Dictionary<string, Icon> icons, List<string> extensions)
        {
            if (worker.CancellationPending)
            {
                return;
            }

            this.AddBooksToFolder(folder, icons, extensions);
            worker.ReportProgress(0, folder);

            string[] subDirectories;
            try
            {
                subDirectories = Directory.GetDirectories(folder.FolderPath);
            }
            catch (Exception ex)
            {
                Trace.TraceError("Error getting subdirectories: {0}", ex.Message);
                return;
            }

            foreach (string subDirectory in subDirectories)
            {
                if (!Directory.Exists(subDirectory))
                {
                    continue;
                }

                var newSubfolder = new Folder(subDirectory);
                this.FillDirectories(worker, newSubfolder, icons, extensions);
                if (newSubfolder.Books.Any() || newSubfolder.SubFolders.Any())
                {
                    folder.SubFolders.Add(newSubfolder);
                }
            }
        }

        /// <summary>
        /// The filter books.
        /// </summary>
        /// <param name="folders">
        /// The folders.
        /// </param>
        /// <returns>
        /// The collection.
        /// </returns>
        private List<Folder> FilterBooksByExtension(List<Folder> folders)
        {
            string searchPattern = this.comboExtensions.SelectedItem.ToString();
            if (!this.isFilteredByExtension)
            {
                return folders;
            }

            var returningList = new List<Folder>();

            foreach (Folder folder in folders)
            {
                var newFolder = new Folder(folder.FolderPath);
                foreach (Book book in folder.Books)
                {
                    bool bookExtensionMatch = string.Equals(
                        book.Extension, 
                        searchPattern, 
                        StringComparison.OrdinalIgnoreCase);
                    if (bookExtensionMatch)
                    {
                        newFolder.Books.Add(book);
                    }
                }

                if (newFolder.Books.Any())
                {
                    returningList.Add(newFolder);
                }
            }

            return returningList;
        }

        /// <summary>
        /// The filter books.
        /// </summary>
        /// <param name="folders">
        /// The folders.
        /// </param>
        /// <returns>
        /// The collection.
        /// </returns>
        private List<Folder> FilterBooksByNameAndFolder(List<Folder> folders)
        {
            string searchPattern = this.txtFilter.Text;
            if (string.IsNullOrEmpty(searchPattern))
            {
                return folders;
            }

            var returningList = new List<Folder>();

            foreach (Folder folder in folders)
            {
                if (this.filterByFolderName)
                {
                    bool folderNameMatchPattern = folder.FolderName.IndexOf(
                        searchPattern, 
                        StringComparison.OrdinalIgnoreCase) >= 0;
                    if (folderNameMatchPattern)
                    {
                        returningList.Add(folder);
                    }
                }
                else
                {
                    var newFolder = new Folder(folder.FolderPath);
                    foreach (Book book in folder.Books)
                    {
                        bool bookNameMatchPattern = book.NameAndExtension.IndexOf(
                            searchPattern, 
                            StringComparison.OrdinalIgnoreCase) >= 0;
                        if (bookNameMatchPattern)
                        {
                            newFolder.Books.Add(book);
                        }
                    }

                    if (newFolder.Books.Any())
                    {
                        returningList.Add(newFolder);
                    }
                }
            }

            return returningList;
        }

        /// <summary>
        /// Gets the folders with books.
        /// </summary>
        /// <param name="returnFolders">
        /// The return folders.
        /// </param>
        /// <param name="currentFolder">
        /// The current folder.
        /// </param>
        private void GetFoldersWithBooks(List<Folder> returnFolders, Folder currentFolder)
        {
            if (currentFolder.Books.Any())
            {
                var newFolder = new Folder(currentFolder.FolderPath)
                                    {
                                        Books =
                                            this.sortByExtension
                                                ? currentFolder.Books.OrderBy(
                                                    b => b.Extension).ToList()
                                                : currentFolder.Books.OrderBy(
                                                    b => b.Name).ToList()
                                    };
                returnFolders.Add(newFolder);
            }

            foreach (Folder subFolder in currentFolder.SubFolders)
            {
                this.GetFoldersWithBooks(returnFolders, subFolder);
            }
        }

        /// <summary>
        /// Handles the RowsRemoved event of the GridBooks control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="DataGridViewRowsRemovedEventArgs"/> instance containing the event data.
        /// </param>
        private void GridBooks_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
        {
            this.lblTotalBooks.Text = this.lblFilteredBooks.Text = string.Format("0");
        }

        /// <summary>
        /// Handles the SizeChanged event of the GridBooks control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void GridBooks_SizeChanged(object sender, EventArgs e)
        {
            this.lblStatus.Width = this.gridBooks.Width - 160;
        }

        /// <summary>
        /// Links the LBL deselect all_ link clicked.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event
        ///     data.
        /// </param>
        private void LinkLblDeselectAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            foreach (Label label in this.ExtensionsLabels)
            {
                label.Font = new Font(label.Font, FontStyle.Regular);
            }
        }

        /// <summary>
        /// Handles the LinkClicked event of the LinkLblSelectAll control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="LinkLabelLinkClickedEventArgs"/> instance containing the event data.
        /// </param>
        private void LinkLblSelectAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            foreach (Label label in this.ExtensionsLabels)
            {
                label.Font = new Font(label.Font, FontStyle.Bold);
            }
        }

        /// <summary>
        /// The main form_ load.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            string applicationFolderPath = Path.GetDirectoryName(Application.ExecutablePath);
            this.txtSTDUViewerPath.Text = string.Concat(applicationFolderPath, "\\STDU\\STDUViewerApp.exe");
            this.txtLibraryPath.Text = string.Concat(applicationFolderPath, "\\Library");
            this.lblTotalBooks.Text = this.lblFilteredBooks.Text = string.Format("0");
            this.lblStatus.Text = string.Format("Ready.");
            this.BindExtensionsCombobox();
        }

        /// <summary>
        /// TXTs the filter_ text changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The <see cref="System.EventArgs"/> instance containing the event data.
        /// </param>
        private void TxtFilter_TextChanged(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(this.txtFilter.Text))
            {
                this.isFiltered = true;
            }
            else
            {
                this.isFiltered = this.comboExtensions.SelectedIndex != 0;
            }

            this.BindData();
        }

        /// <summary>
        ///     The update books count.
        /// </summary>
        private void UpdateBooksCount()
        {
            this.lblTotalBooks.Text = this.TotalBooksCount.ToString(CultureInfo.InvariantCulture);
            this.lblFilteredBooks.Text = this.FilteredBooksCount.ToString(CultureInfo.InvariantCulture);
        }

        #endregion
    }
}